import Scanner from './Scanner';


function tokenizer(tplt) {
  const scanner = new Scanner(tplt.trim());

  // 收集tokens，并将循环内容嵌套到tokens中，并返回
  return nestTokens(collectTokens(scanner));
}

function collectTokens(scanner) {
  const tokens = [];
  let word = '';
  // 当scanner没有到头的就持续将获取的token加入数组中
  while (!scanner.eos()) {
    // 收集文本
    word = scanner.scanUntil('{{');
    word && tokens.push(['text', word]);
    scanner.scan('{{');

    // 收集变量
    word = scanner.scanUntil('}}');

    // 对不同类型结构进行分类标识
    switch (word[0]) {
      case '#':
        tokens.push(['#', word.substring(1)]);
        break;
      case '/':
        tokens.push(['/', word.substring(1)]);
        break;
      default:
        word && tokens.push(['name', word]);
    }

    scanner.scan('}}');
  }

  return tokens;
}

function nestTokens(tokens) {

  // const nestedTokens = [];
  // // 默认将最外层作用域，当前为空，压入栈中
  // const stack = [nestedTokens];

  // for (let i = 0, len = tokens.length; i < len; i++) {
  //   const token = tokens[i];
  //   // 将栈顶(最后一项)也就是当前作用域拿出
  //   // 用来收集所有属于当前作用域的token
  //   const collector = stack[stack.length - 1][2] || nestedTokens;
  //   // 闭合token不用添加
  //   token[0] !== '/' && collector.push(token);
  //   // 根据token第一项进行压栈和出栈操作
  //   switch (token[0]) {
  //     case '#':
  //       stack.push(token);
  //       // 新建一个空数组保存嵌套结构
  //       token[2] = [];
  //       break;
  //     case '/':
  //       stack.pop();
  //       break;
  //   }
  // }

  // return nestedTokens;

  /*-------------------------OR---------------------------*/

  const nestedTokens = [];
  const stack = [];
  // 收集器默认为最外层
  let collector = nestedTokens;

  for (let i = 0, len = tokens.length; i < len; i++) {
    const token = tokens[i];

    switch (token[0]) {
      case '#':
        // 收集当前token
        collector.push(token);
        // 压入栈中
        stack.push(token);
        // 由于进入了新的嵌套结构，新建一个数组保存嵌套结构
        // 并修改collector的指向
        collector = token[2] = [];
        break;
      case '/':
        // 出栈
        stack.pop();
        // 将收集器指向上一层作用域中用于存放嵌套结构的数组
        collector = stack.length > 0 
                    ? stack[stack.length - 1][2] 
                    : nestedTokens;
        break;
      default:
        collector.push(token);
    }
  }

  return nestedTokens;
}

export default tokenizer;
